/* Copyright (C) 2024 wlly-lzh
 * Created On 24/03/12
 * Singly Linked List  单链表(封装)
 * */

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "singly_linked_list.c"
typedef struct LSLList LSLList;
struct LSLList {
	Singly_Linked_List * Head;
	Singly_Linked_List * Tail;
	unsigned int Length;
};

bool AddHead_LSLList(LSLList *List,void *Data);
bool AddTail_LSLList(LSLList *List,void *Data);
void Error_LSLList_NULL();
void Error_LSLList_Over();
void Error_LSLList_Malloc();

LSLList * Create_LSLList(){
    LSLList *newList=(LSLList *)malloc(sizeof(struct LSLList));
	if(newList == NULL){
		Error_LSLList_Malloc();
		exit(3);
	}
	newList->Head=NULL; newList->Tail=NULL;
	newList->Length=0;
    return newList;
}
bool Destroy_LSLList(LSLList **List,void (*FreeData)(void *)){
	if(*List != NULL){
		Destroy_SLList((*List)->Head,FreeData);
		free(*List);
		*(List)=NULL;
		return true;
	}else{
		Error_LSLList_NULL();
		exit(4);
	}
}
bool Clear_LSLList(LSLList *List,void (*FreeData)(void*)){
	if(List != NULL){
		Destroy_SLList(List->Head,FreeData);
		List->Head=NULL;
		List->Tail=NULL;
		List->Length=0;
		return true;
	}else{
		Error_LSLList_NULL();
		exit(4);
	}
}
bool Insert_LSLList(LSLList *List,unsigned int addr,void *Data){
	if(List == NULL){ //检查参数的合法性
		Error_LSLList_NULL();
		exit(4);
	}else if(Data == NULL){
		Error_LSLList_NULL();
		return false;
	}
	if(addr == 0 || addr > (List->Length)+1){
		Error_LSLList_Over();
		return false;
	}
	SLList * newList;
	if(List->Length > 0){
		if(addr > 1 && addr <=List->Length){  //在中间插入
			Insert_SLList(List->Head,addr,Data);
		}else if(addr == 1){                  //在头部插入
			AddHead_LSLList(List,Data);
		}else if(addr == List->Length+1){     //在尾部插入
			AddTail_LSLList(List,Data);
		}
		(List->Length)++;
		return true;
	}else{   // 第一次进行插入操作，此时表中没有元素
		newList=(SLList *)malloc(sizeof(SLList));
		if(newList == NULL){    // 按照规矩进行分配失败处理
			Error_LSLList_Malloc();   exit(3);
		}
		newList->Data=Data;
		newList->Next=NULL;
		List->Head=newList;
		List->Tail=newList;
		return true;
	}
}
bool Delete_LSLList(LSLList *List,unsigned int addr,
		void (*FreeData)(void *)){
	if(List != NULL){
		if(addr > 1 && addr < List->Length){ // 删中间
			Delete_SLList(List->Head,addr,FreeData);
		}else if(addr == 1){  // 删头
			SLList *Del=List->Head;
			List->Head=List->Head->Next;
			FreeData(Del->Data);
			free(Del);
		}else if(addr == List->Length && addr > 0){  // 删尾
			SLList *newLast;
			GetNode_SLList(List->Head,addr-1,&newLast);
			newLast->Next=NULL;
			FreeData((List->Tail)->Data);
			free(List->Tail);
			List->Tail=newLast;
		}else{
			Error_LSLList_Over();
			return false;
		}
		(List->Length)--;
		return true;
	}else{
		Error_LSLList_NULL();
		exit(4);
	}
}
unsigned int Length_LSLList(const LSLList * List){
	if(List != NULL){
		return List->Length;
	}else{
		Error_LSLList_NULL();
		exit(4);
	}
}
bool GetItem_LSLList(const LSLList *List, unsigned int addr,void **Data){
	if(List == NULL){
		Error_LSLList_NULL();
		exit(4);
	}
	if(addr > 0 && addr <= List->Length){
		SLList * Note;
		GetNode_SLList(List->Head,addr,&Note);
		*Data=Note->Data;
		return true;
	}else{
		Error_LSLList_Over();
		return false;
	}
}
bool Update_LSLList(LSLList *List, unsigned int addr, void *Data,
		void (*FreeData)(void *)){
	if(List == NULL){
		Error_LSLList_NULL();
		exit(4);
	}
	if(Data != NULL){
		if(addr >0 && addr <= List->Length){
			Update_SLList(List->Head,addr,Data,FreeData);
			return true;
		}else{
			Error_LSLList_Over();
			return false;
		}
	}else{
		Error_LSLList_NULL();
		return false;
	}
}
bool AddHead_LSLList(LSLList *List,void *Data){
	if(List == NULL){
		Error_LSLList_NULL();
		exit(4);
	}else if(Data == NULL){
		Error_LSLList_NULL();
		return false;
	}
	SLList * newList;
	newList=(SLList *)malloc(sizeof(SLList));
	if(newList == NULL){
		Error_LSLList_Malloc();
		exit(3);
	}
	newList->Data=Data;
	newList->Next=List->Head;
	if(List->Length != 0){
		List->Head=newList;
		(List->Length)++;
		return true;
	}else{
		List->Head=newList;
		List->Tail=newList;
		(List->Length)++;
		return true;
	}
}
bool AddTail_LSLList(LSLList *List,void *Data){
	if(List == NULL){
		Error_LSLList_NULL();
		exit(4);
	}else if(Data == NULL){
		Error_LSLList_NULL();
		return false;
	}
	SLList * newList;
	newList=(SLList *)malloc(sizeof(SLList));
	if(newList == NULL){
		Error_LSLList_Malloc();
		exit(3);
	}
	newList->Data=Data;
	newList->Next=NULL;
	if(List->Length != 0){
		List->Tail->Next=newList;
		List->Tail=newList;
		(List->Length)++;
	}else{
		List->Head=newList;
		List->Tail=newList;
		(List->Length)++;
	}
	return true;
}

#ifdef _LINUX_PLATFORM_
void Error_LSLList_NULL(){
	fprintf(stderr,"\e[31mliblds/LSLList: Your parameter Is Null!\e[0m\n");
}
void Error_LSLList_Over(){
	fprintf(stderr,"\e[31mliblds/LSLList: Addr over the bounds!\e[0m\n");
}
void Error_LSLList_Malloc(){
	fprintf(stderr,"\e[31mliblds/LSLList: Malloc False!\e[0m\n");
}
#else
void Error_LSLList_NULL(){
	fprintf(stderr,"liblds/LSLList: Your parameter Is Null!\n");
}
void Error_LSLList_Over(){
	fprintf(stderr,"liblds/LSLList: Addr over the bounds!\n");
}
void Error_LSLList_Malloc(){
	fprintf(stderr,"liblds/LSLList: Malloc False!\n");
}
#endif
